/*
 * Copyright (c) Huawei Device Co., Ltd. 2023. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "channel_proxy.h"
#include "common_utils.h"
#include "loghelper.h"
#include "message_option.h"
#include "message_parcel.h"
#include "se_service_ipc_interface_code.h"

namespace OHOS {
namespace SE {
namespace OMAPI {

ErrorCode ChannelProxy::Close()
{
    MessageParcel data;
    MessageParcel reply;
    MessageOption option(MessageOption::TF_SYNC);
    int statusCode = SE_SUCCESS;
    if (!data.WriteInterfaceToken(GetDescriptor())) {
        ErrorLog("Close Write interface token error");
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    int res = Remote()->SendRequest(static_cast<uint32_t>(SeServiceIpcInterfaceCode::COMMAND_CHANNEL_CLOSE),
        data, reply, option);
    if (res != ERR_NONE) {
        ErrorLog("[ChannelProxy::Close] send request(%{public}d) with Res(%{public}d) fail.",
            SeServiceIpcInterfaceCode::COMMAND_CHANNEL_CLOSE, res);
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    statusCode = reply.ReadInt32();
    return CommonUtils::IntToErrorCode(statusCode);
}

ErrorCode ChannelProxy::IsClosed(bool &isClosed)
{
    MessageParcel data;
    MessageParcel reply;
    MessageOption option(MessageOption::TF_SYNC);
    int statusCode = SE_SUCCESS;
    if (!data.WriteInterfaceToken(GetDescriptor())) {
        ErrorLog("IsClosed Write interface token error");
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    int res = Remote()->SendRequest(static_cast<uint32_t>(SeServiceIpcInterfaceCode::COMMAND_CHANNEL_IS_CLOSED),
        data, reply, option);
    if (res != ERR_NONE) {
        ErrorLog("[ChannelProxy::IsClosed] send request(%{public}d) with Res(%{public}d) fail.",
            SeServiceIpcInterfaceCode::COMMAND_CHANNEL_IS_CLOSED, res);
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    InfoLog("[ChannelProxy::IsClosed] send request(%{public}d) with Res(%{public}d) success.",
        SeServiceIpcInterfaceCode::COMMAND_CHANNEL_IS_CLOSED, res);
    isClosed = reply.ReadBool();
    statusCode = reply.ReadInt32();
    return CommonUtils::IntToErrorCode(statusCode);
}

ErrorCode ChannelProxy::IsBasicChannel(bool &isBasicChannel)
{
    MessageParcel data;
    MessageParcel reply;
    MessageOption option(MessageOption::TF_SYNC);
    int statusCode = SE_SUCCESS;
    isBasicChannel = false;
    if (!data.WriteInterfaceToken(GetDescriptor())) {
        ErrorLog("IsBasicChannel Write interface token error");
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    int res = Remote()->SendRequest(static_cast<uint32_t>(SeServiceIpcInterfaceCode::COMMAND_CHANNEL_IS_BASIC_CHANNEL),
        data, reply, option);
    if (res != ERR_NONE) {
        ErrorLog("[ChannelProxy::IsBasicChannel] send request(%{public}d) with Res(%{public}d) fail.",
            SeServiceIpcInterfaceCode::COMMAND_CHANNEL_IS_BASIC_CHANNEL, res);
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    InfoLog("[ChannelProxy::IsBasicChannel] send request(%{public}d) with Res(%{public}d) success.",
        SeServiceIpcInterfaceCode::COMMAND_CHANNEL_IS_BASIC_CHANNEL, res);
    isBasicChannel = reply.ReadBool();
    statusCode = reply.ReadInt32();
    return CommonUtils::IntToErrorCode(statusCode);
}
ErrorCode ChannelProxy::GetSelectResponse(std::string &selectResponse)
{
    MessageParcel data;
    MessageParcel reply;
    MessageOption option(MessageOption::TF_SYNC);
    int statusCode = SE_SUCCESS;
    selectResponse = std::string{};
    if (!data.WriteInterfaceToken(GetDescriptor())) {
        ErrorLog("GetSelectResponse Write interface token error");
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    int res = Remote()->SendRequest(
        static_cast<uint32_t>(SeServiceIpcInterfaceCode::COMMAND_CHANNEL_GET_SELECT_RESPONSE), data, reply, option);
    if (res != ERR_NONE) {
        ErrorLog("[ChannelProxy::GetSelectResponse] send request(%{public}d) with Res(%{public}d) fail.",
            SeServiceIpcInterfaceCode::COMMAND_CHANNEL_GET_SELECT_RESPONSE, res);
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    InfoLog("[ChannelProxy::GetSelectResponse] send request(%{public}d) with Res(%{public}d) success.",
        SeServiceIpcInterfaceCode::COMMAND_CHANNEL_GET_SELECT_RESPONSE, res);
    selectResponse = reply.ReadString();
    statusCode = reply.ReadInt32();
    return CommonUtils::IntToErrorCode(statusCode);
}
ErrorCode ChannelProxy::Transmit(const std::string &command, std::string& response)
{
    MessageParcel data;
    MessageParcel reply;
    MessageOption option(MessageOption::TF_SYNC);
    int statusCode = SE_SUCCESS;
    response = std::string{};
    if (!data.WriteInterfaceToken(GetDescriptor())) {
        ErrorLog("Transmit Write interface token error");
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    data.WriteString(command);
    int res = Remote()->SendRequest(static_cast<uint32_t>(SeServiceIpcInterfaceCode::COMMAND_CHANNEL_TRANSMIT),
        data, reply, option);
    if (res != ERR_NONE) {
        ErrorLog(
            "[ChannelProxy::Transmit] send request(%{public}d) with Res(%{public}d) fail.",
            SeServiceIpcInterfaceCode::COMMAND_CHANNEL_TRANSMIT, res);
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    InfoLog("[ChannelProxy::Transmit] send request(%{public}d) with Res(%{public}d) success.",
        SeServiceIpcInterfaceCode::COMMAND_CHANNEL_TRANSMIT, res);
    response = reply.ReadString();
    statusCode = reply.ReadInt32();
    return CommonUtils::IntToErrorCode(statusCode);
}
ErrorCode ChannelProxy::SelectNext(bool &selectStatus)
{
    MessageParcel data;
    MessageParcel reply;
    MessageOption option(MessageOption::TF_SYNC);
    int statusCode = SE_SUCCESS;
    selectStatus = false;
    if (!data.WriteInterfaceToken(GetDescriptor())) {
        ErrorLog("SelectNext Write interface token error");
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    int res = Remote()->SendRequest(static_cast<uint32_t>(SeServiceIpcInterfaceCode::COMMAND_CHANNEL_SELECT_NEXT),
        data, reply, option);
    if (res != ERR_NONE) {
        ErrorLog("[ChannelProxy::SelectNext] send request(%{public}d) with Res(%{public}d) fail.",
            SeServiceIpcInterfaceCode::COMMAND_CHANNEL_SELECT_NEXT, res);
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    InfoLog("[ChannelProxy::SelectNext] send request(%{public}d) with Res(%{public}d) success.",
        SeServiceIpcInterfaceCode::COMMAND_CHANNEL_SELECT_NEXT, res);
    selectStatus = reply.ReadBool();
    statusCode = reply.ReadInt32();
    return CommonUtils::IntToErrorCode(statusCode);
}

ErrorCode ChannelProxy::GetChannelNumber(uint8_t &channelNumber)
{
    // DONOT supported for application.
    channelNumber = 0;
    return ErrorCode::SE_SUCCESS;
}
}  // namespace OMAPI
}  // namespace SE
}  // namespace OHOS